package com.xique.door.biz.service.impl;

import com.github.pagehelper.PageInfo;
import com.xique.common.core.constant.AdvertFileType;
import com.xique.common.core.constant.AdvertStatus;
import com.xique.common.core.constant.HttpStatus;
import com.xique.common.core.constant.OssFilePrefixConstants;
import com.xique.common.core.utils.*;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.core.web.page.TableDataInfo;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.request.advert.AdvertAddRequest;
import com.xique.door.bean.request.advert.AdvertDownRequest;
import com.xique.door.bean.request.advert.AdvertSearchRequest;
import com.xique.door.bean.request.advert.AdvertUpdateRequest;
import com.xique.door.bean.vo.ParkInfoIssueVO;
import com.xique.door.bean.vo.advert.DoorAdvertCommandVo;
import com.xique.door.bean.vo.advert.DoorAdvertVo;
import com.xique.door.biz.service.IDoorAdvertBizService;
import com.xique.door.command.IAdvertCommandBizService;
import com.xique.door.constant.AccessCommandConstant;
import com.xique.door.device.freeview.constant.CommandStatus;
import com.xique.door.service.IAccessDeviceService;
import com.xique.door.service.IDAdvertService;
import com.xique.door.service.IDDeviceAdvertService;
import com.xique.door.service.IParkInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: caogq
 * @Date: 2022/3/13 10:51
 * @Description:
 */
@Service
public class DoorAdvertBizServiceImpl implements IDoorAdvertBizService {
    @Autowired
    private AliossUtil aliossUtil;

    @Autowired
    private IDAdvertService advertService;

    @Autowired
    private IAdvertCommandBizService advertCommandBizService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Autowired
    private IDDeviceAdvertService deviceAdvertService;

    @Autowired
    private IDAdvertService dAdvertService;

    @Autowired
    private IParkInfoService parkInfoService;


    @Override
    @Transactional
    public AjaxResult addAdvert(AdvertAddRequest request) {
        //1、广告上传到oss，返回访问路径
        String prefix = OssFilePrefixConstants.DOOR_ADVERT_IMGAGE;
        if (request.getFileType().equals(AdvertFileType.VIDEO)) {
            prefix = OssFilePrefixConstants.DOOR_ADVERT_VIDEO;
        }
        Map<String, Object> upload = aliossUtil.uploadFile(request.getFile(), prefix);
        //2、新增广告表
        DAdvert advert = OrikaUtil.convert(request, DAdvert.class);
        advert.setEndTime(DateUtils.getEndOfDay(advert.getEndTime()));
        advert.setStartTime(DateUtils.getStartOfDay(advert.getStartTime()));
//        this.updateAdvertStatus(advert);
        advert.setUrl(String.valueOf(upload.get("url")));
        advertService.insertDAdvert(advert);
        //3、新增广告设备表
        List<AccessDevice> accessDevices = null;
        if (request.getDeviceIds() != null) {
            AccessDevice accessDevice = new AccessDevice();
            accessDevice.setModel(AccessCommandConstant.DeviceType.FREEVIEW_32);
            accessDevice.setOnlineStatus("online");
            accessDevices = accessDeviceService.selectAccessDeviceListIds(request.getDeviceIds(), accessDevice);
        } else {
            AccessDevice accessDevice = new AccessDevice();
            accessDevice.setModel(AccessCommandConstant.DeviceType.FREEVIEW_32);
            accessDevice.setOnlineStatus("online");
            accessDevices = accessDeviceService.selectAccessDeviceList(accessDevice);
        }
        if (accessDevices.isEmpty()) {
            return AjaxResult.success("设备不在线");
        }
        List<DDeviceAdvert> deviceAdverts = new ArrayList<>();
        for (AccessDevice device : accessDevices) {
            DDeviceAdvert deviceAdvert = new DDeviceAdvert();
            deviceAdvert.setStatus(CommandStatus.SEND);
            deviceAdvert.setDevSn(device.getDevSn());
            deviceAdvert.setAdvertId(advert.getId());
            deviceAdvert.setDeviceId(device.getId());
            deviceAdvert.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
            deviceAdvert.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
            deviceAdverts.add(deviceAdvert);
        }
        int i = deviceAdvertService.batchInsert(deviceAdverts);
        //4、下发
        List<String> devSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        Object obj = advertCommandBizService.downAdvert(advert, devSns);

        return AjaxResult.success();
    }

    @Override
    @Transactional
    public AjaxResult FixedInvestmentAddAdvert(AdvertAddRequest request) {
        //1、广告上传到oss，返回访问路径
        String prefix = OssFilePrefixConstants.DOOR_ADVERT_IMGAGE;
        if (request.getFileType().equals(AdvertFileType.VIDEO)) {
            prefix = OssFilePrefixConstants.DOOR_ADVERT_VIDEO;
        }
        Map<String, Object> upload = aliossUtil.uploadFile(request.getFile(), prefix);
        //2、新增广告表
        DAdvert advert = OrikaUtil.convert(request, DAdvert.class);
        advert.setEndTime(DateUtils.getEndOfDay(advert.getEndTime()));
        advert.setStartTime(DateUtils.getStartOfDay(advert.getStartTime()));
//        this.updateAdvertStatus(advert);
        advert.setUrl(String.valueOf(upload.get("url")));
        advertService.insertDAdvert(advert);
        //3、新增广告设备表
        AccessDevice accessDevice = new AccessDevice();
        accessDevice.setModel(AccessCommandConstant.DeviceType.FREEVIEW_32);
        accessDevice.setOnlineStatus("online");
        List<AccessDevice> accessDevices = accessDeviceService.selectAccessDeviceList(accessDevice);
        if (accessDevices.isEmpty()) {
            return AjaxResult.success("设备不在线");
        }
        List<DDeviceAdvert> deviceAdverts = new ArrayList<>();
        for (AccessDevice device : accessDevices) {
            DDeviceAdvert deviceAdvert = new DDeviceAdvert();
            deviceAdvert.setStatus(CommandStatus.SEND);
            deviceAdvert.setDevSn(device.getDevSn());
            deviceAdvert.setAdvertId(advert.getId());
            deviceAdvert.setDeviceId(device.getId());
            deviceAdvert.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
            deviceAdvert.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
            deviceAdverts.add(deviceAdvert);
        }
        int i = deviceAdvertService.batchInsert(deviceAdverts);
        //4、下发
        List<String> devSns = accessDevices.stream().map(AccessDevice::getDevSn).collect(Collectors.toList());
        Object obj = advertCommandBizService.downAdvert(advert, devSns);

        return AjaxResult.success();
    }


    @Override
    public TableDataInfo conditionSearchAdvertList(AdvertSearchRequest request) {
        List<DAdvert> list = dAdvertService.conditionSearchAdvertList(request);

        List<Long> advertIds = list.stream().map(DAdvert::getId).collect(Collectors.toList());
        DDeviceAdvert deviceAdvertSearch = new DDeviceAdvert();
        deviceAdvertSearch.setAdvertIds(advertIds);
        List<DDeviceAdvert> deviceAdverts = deviceAdvertService.selectDDeviceAdvertList(deviceAdvertSearch);

        List<Long> deviceIds = deviceAdverts.stream().map(DDeviceAdvert::getDeviceId).collect(Collectors.toList());
        List<AccessDevice> accessDevices = accessDeviceService.selectAccessDeviceByIds(deviceIds);

        List<Long> parkIds = accessDevices.stream().map(AccessDevice::getParkId).collect(Collectors.toList());
        List<ParkInfo> parkInfos = parkInfoService.selectParkInfoByIds(parkIds);

        List<DoorAdvertVo> advertVos = OrikaUtil.converts(list, DoorAdvertVo.class);
        for (DoorAdvertVo advertVo : advertVos) {
            List<DDeviceAdvert> commandRecordDtOs = deviceAdverts.stream().filter(e -> e.getAdvertId().equals(advertVo.getId())).collect(Collectors.toList());
            List<DoorAdvertCommandVo> commandRecordVos = OrikaUtil.converts(commandRecordDtOs, DoorAdvertCommandVo.class);
            commandRecordVos.forEach(commandRecordVo -> {
                AccessDevice accessDevice = accessDevices.stream().filter(e -> e.getId().equals(commandRecordVo.getDeviceId())).findAny().orElse(null);
                if (accessDevice != null) {
                    commandRecordVo.setDeviceName(accessDevice.getName());
                    ParkInfo parkInfo = parkInfos.stream().filter(e -> e.getId().equals(accessDevice.getParkId())).findAny().orElse(null);
                    commandRecordVo.setParkName(parkInfo.getName());
                    commandRecordVo.setProvince(parkInfo.getProvince());
                    commandRecordVo.setCity(parkInfo.getCity());
                    commandRecordVo.setDistrict(parkInfo.getDistrict());
                }
            });
            List<DoorAdvertCommandVo> errorRecords = commandRecordVos.stream().filter(e -> !CommandStatus.SUCCESS.equals(e.getStatus())).collect(Collectors.toList());
            advertVo.setCommandStatus(errorRecords.isEmpty() ? 0 : 1);
            advertVo.setCommandVos(commandRecordVos);
            if (StringUtils.isEmpty(advertVo.getStatus())) {
                advertVo.setStatus(this.selectAdvertStatus(advertVo.getStartTime(), advertVo.getEndTime()));
            }
        }
        List<DoorAdvertVo> advertVoList = new ArrayList<>();
        List<DoorAdvertVo> advertVoList2 = new ArrayList<>();
        for (int i = 0; i < advertVos.size(); i++) {
            DoorAdvertVo advertVo = advertVos.get(i);
            if (advertVo.getStatus().equals("2")) {
                advertVoList.add(advertVo);
            } else {
                advertVoList2.add(advertVo);
            }
        }
        Collections.reverse(advertVoList);
        advertVoList.addAll(advertVoList2);
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(advertVoList);
        rspData.setMsg("查询成功");
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }

    @Override
    public AjaxResult down(AdvertDownRequest request) {
        DAdvert advert = advertService.selectDAdvertById(request.getAdvertId());
        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(request.getDeviceId());
        Object obj = advertCommandBizService.downAdvert(advert, Collections.singletonList(accessDevice.getDevSn()));
        return AjaxResult.success();
    }


    @Override
    public AjaxResult delete(AdvertDownRequest request) {
        DAdvert advert = advertService.selectDAdvertById(request.getAdvertId());
        advert.setStatus("4");
        advertService.updateDAdvert(advert);
        AccessDevice search = new AccessDevice();
        search.setModel(AccessCommandConstant.DeviceType.FREEVIEW_32);
        List<AccessDevice> accessDeviceList = accessDeviceService.selectAccessDeviceList(search);
        Object obj = advertCommandBizService.deleteAdvert(advert, accessDeviceList.stream().map(AccessDevice::getDevSn).collect(Collectors.toList()));
        return AjaxResult.success();
    }

    @Override
    public AjaxResult deleteOne(List<Long> ids, Long advertId) {
        if (ids != null && ids.size() > 0) {
            List<String> devSns = new ArrayList<>();
            ids.forEach(id -> {
                DDeviceAdvert dDeviceAdvert = deviceAdvertService.selectDDeviceAdvertById(id);
                AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(dDeviceAdvert.getDeviceId());
                devSns.add(accessDevice.getDevSn());
                DDeviceAdvert deviceAdvert = new DDeviceAdvert();
                deviceAdvert.setId(id);
                deviceAdvert.setDelFlag(1);
                deviceAdvertService.updateDDeviceAdvert(deviceAdvert);
            });
            DAdvert advert = advertService.selectDAdvertById(advertId);
            Object obj = advertCommandBizService.deleteAdvert(advert, devSns);
            return AjaxResult.success();
        }

        return AjaxResult.error("参数为空");
    }

    @Override
    public AjaxResult downs(List<Long> ids, Long advertId) {
        if (ids != null && ids.size() > 0) {
            List<String> devSns = new ArrayList<>();
            ids.forEach(id -> {
                DDeviceAdvert dDeviceAdvert = deviceAdvertService.selectDDeviceAdvertById(id);
                AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(dDeviceAdvert.getDeviceId());
                devSns.add(accessDevice.getDevSn());
                if (dDeviceAdvert.getDelFlag() == 1) {
                    DDeviceAdvert deviceAdvert = new DDeviceAdvert();
                    deviceAdvert.setId(id);
                    deviceAdvert.setDelFlag(0);
                    deviceAdvertService.updateDDeviceAdvert(deviceAdvert);
                }
            });
            DAdvert advert = advertService.selectDAdvertById(advertId);
            Object obj = advertCommandBizService.downAdvert(advert, devSns);
            return AjaxResult.success();
        }
        return AjaxResult.error("参数为空");
    }

    @Override
    public AjaxResult details(AdvertSearchRequest request) {
        DAdvert advert = advertService.selectDAdvertById(request.getId());
        DDeviceAdvert deviceAdvertSearch = new DDeviceAdvert();
        deviceAdvertSearch.setAdvertId(advert.getId());
        List<DDeviceAdvert> deviceAdverts = deviceAdvertService.selectDDeviceAdvertList(deviceAdvertSearch);
        if (advert != null && advert.getOnlineType().equals("2") && deviceAdverts.size() > 0) {
            List<Long> deviceIds = deviceAdverts.stream().map(DDeviceAdvert::getDeviceId).collect(Collectors.toList());
            List<ParkInfoIssueVO> vos = accessDeviceService.selectIssuedAccessDevice(deviceIds);
            advert.setListvo(vos);
        }
        return AjaxResult.success(advert);

    }


    @Override
    @Transactional
    public AjaxResult updateAdvert(AdvertUpdateRequest request) {
        DAdvert adverts = advertService.selectDAdvertById(request.getId());
        DAdvert advert = OrikaUtil.convert(request, DAdvert.class);
        //1、基础表处理
        if (request.getFile() != null) {
            String prefix = OssFilePrefixConstants.DOOR_ADVERT_IMGAGE;
            if (request.getFileType().equals(AdvertFileType.VIDEO)) {
                prefix = OssFilePrefixConstants.DOOR_ADVERT_VIDEO;
            }
            Map<String, Object> upload = aliossUtil.uploadFile(request.getFile(), prefix);
            advert.setUrl(String.valueOf(upload.get("url")));
        }
//        String status = this.selectAdvertStatus(advert);
//        advert.setStatus(status);
        advertService.updateDAdvert(advert);

        //2、中间表处理
        DDeviceAdvert deviceAdvert = new DDeviceAdvert();
        deviceAdvert.setAdvertId(request.getId());
        List<Long> advertIds = request.getDeviceIds();
        List<Long> deviceAdvertId = new ArrayList<>();
        if (adverts != null && adverts.getOnlineType().equals("1") && advertIds.size() > 0) {
            return AjaxResult.success("统一投放，禁止修改设备");
        }
        if (advertIds.size() > 0) {
            List<String> devSns = new ArrayList<>();
            for (Long deviceId : advertIds) {
                deviceAdvert.setDeviceId(deviceId);

                List<DDeviceAdvert> deviceAdverts = deviceAdvertService.selectDDeviceAdvertList(deviceAdvert);
                if (deviceAdverts.size() > 0) {
                    deviceAdverts.forEach(e -> {
                        deviceAdvertId.add(e.getId());
                        e.setStatus(CommandStatus.SEND);
                        e.setUpdateTime(new Date());
                        e.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
                    });
                    deviceAdvertService.batchUpdate(deviceAdverts);
                } else {
                    DDeviceAdvert deviceAdve = new DDeviceAdvert();
                    deviceAdve.setStatus(CommandStatus.SEND);
                    AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(deviceId);
                    deviceAdve.setDevSn(accessDevice.getDevSn());
                    deviceAdve.setAdvertId(advert.getId());
                    deviceAdve.setDeviceId(deviceId);
                    deviceAdve.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
                    deviceAdve.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
                    deviceAdverts.add(deviceAdve);
                    int i = deviceAdvertService.batchInsert(deviceAdverts);
                    deviceAdvertId.add(deviceAdve.getId());
                }
                devSns = deviceAdverts.stream().map(DDeviceAdvert::getDevSn).collect(Collectors.toList());

            }
            //3、下发
            Object obj = advertCommandBizService.downAdvert(advert, devSns);
        }
        if (deviceAdvertId.size() > 0) {
            List<DDeviceAdvert> deviceAdvertList = deviceAdvertService.selectNotDDeviceAdvert(deviceAdvertId, request.getId());
            List<String> devSns = new ArrayList<>();
            if (deviceAdvertList.size() > 0) {
                deviceAdvertList.forEach(e -> {
                    devSns.add(e.getDevSn());
                    deviceAdvertService.deleteDDeviceAdvertById(e.getId());

                });
                //删除
                Object obj = advertCommandBizService.deleteAdvert(advert, devSns);
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult deleteAdvert(Long id) {
        DAdvert adverts = advertService.selectDAdvertById(id);
        String status = selectAdvertStatus(adverts.getStartTime(), adverts.getEndTime());
        if (status.equals("3") || adverts.getStatus().equals("4")) {
            DAdvert advert = new DAdvert();
            advert.setId(id);
            advert.setDelFlag(1);
            advertService.updateDAdvert(advert);
            DDeviceAdvert deviceAdvert = new DDeviceAdvert();
            deviceAdvert.setAdvertId(advert.getId());
            List<DDeviceAdvert> deviceAdverts = deviceAdvertService.selectDDeviceAdvertList(deviceAdvert);
            if (deviceAdverts != null) {
                for (DDeviceAdvert dDeviceAdvert : deviceAdverts) {
                    deviceAdvertService.deleteDDeviceAdvertById(dDeviceAdvert.getId());
                }
            }

            return AjaxResult.success();
        }
        return AjaxResult.success("未结束或未下架，不能删除");
    }

    private String selectAdvertStatus(Date startTime, Date endTime) {
        String status = AdvertStatus.UNSTART;
//        未开始：当前时间 < 开始时间
//        if (advert.getStartTime().after(DateUtils.getNowDate())) {
//            advert.setStatus(AdvertStatus.UNSTART);
//        }
        //展示中：开始时间 < 当前时间 < 结束时间
        if (startTime.before(DateUtils.getNowDate()) && endTime.after(DateUtils.getNowDate())) {
            status = AdvertStatus.IN;
        }
        //已结束：当前时间>结束时间
        if (endTime.before(DateUtils.getNowDate())) {
            status = AdvertStatus.END;
        }
        return status;
    }


}
